# include <iostream>

// TODO finish it later


class Node {
	public:
		virtual ~Node() {}
};


class Expression : public Node {};
class Term : Node {};
class Condition : Node {};

//==================================================

class ControlStatement : Node {

};

class Statement : Node {
protected:
	Expression *expr;
	ControlStatement *cs;
public:
	Statement(Expression *e, ControlStatement *s): expr(e), cs(s) {};
};

//==================================================

class InstructionsPreamble : Node {};

class DefinitionsPreamble : InstructionsPreamble {};

class Statements : InstructionsPreamble {
protected:
	Expression *expr;
	Statements *statements;
	Statement *statement;
public:
	Statements(Expression *l, Statements *r, Statement *s): expr(l), statements(r), statement(s) {};
};

class Instructions : Node {
protected:
	InstructionsPreamble *left;
	Instructions *right;
public:
	Instructions(InstructionsPreamble *l, Instructions *r): left(l), right(r) {} ;
};

//==================================================

class BooleanCondition : Condition{
protected:
	bool value;
public:
	BooleanCondition(bool v): value(v) {} ;
};

class OperatorCondition : Condition {
protected:
	Expression *left;
	Expression *right;
	int condition_operator;
public:
	OperatorCondition(Expression *L, int op, Expression *R): left(L), condition_operator(op), right(R) {};
};

class Conditions : Node {
protected:
	Condition *left;
	int type;
	Conditions *right;
public:
	Conditions(Condition *l, int t, Conditions *r): left(l), type(t), right(r) {};
};

//==================================================

class TermExpression : Expression {
protected:
	Term *term;
public:
	TermExpression(Term *t): term(t) {};
};

class ActionExpression : Expression {
protected:
	Expression *left;
	int type;
	Term *right;
public:
	ActionExpression(Expression *e, int t, Term *te): left(e), type(t), right(te) {};
};

//==================================================

class Primary : Node {
									// TODO
};


class PrimaryTerm : Term {
protected:
	Primary *primary;
public:
	PrimaryTerm(Primary *p): primary(p) {} ;
};

class ActionTerm : Term {
protected:
	Term *left;
	int type;
	Primary *right;
public:
	ActionTerm(Term *l, int t, Primary *r): left(l), type(t), right(r) {} ;
};

//==================================================

class ListElement : Expression {};

class ListElements : Node {
protected:
	ListElements *left;
	int type;
	ListElement *right;
public:
	ListElements(ListElements *l, int t, ListElement *r): left(l), type(t), right(r) {};
};

class ListDefinition : ListElements {} ;

class MatrixRows : Node {};

class MatrixRowsM : MatrixRows {
protected:
	ListDefinition *left;
	MatrixRows *right;
public:
	MatrixRowsM(ListDefinition *l, MatrixRows *r): left(l), right(r) {};
};

class MatrixRowsL : MatrixRows {
	ListDefinition *left;
	ListDefinition *right;
public:
	MatrixRowsL(ListDefinition *l, ListDefinition *r): left(l), right(r) {};	
};

class MatrixDefinition : MatrixRows {};
  
//==================================================

class Variable : Node {
protected:
	int type;
public:
	Variable(int t): type(t) {};

};